package com.spzx.product.service.impl;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.spzx.product.api.domain.vo.CategoryVo;
import com.spzx.product.domain.Category;
import com.spzx.product.domain.vo.CategoryExcelVo;
import com.spzx.product.helper.CategoryHelper;
import com.spzx.product.mapper.CategoryMapper;
import com.spzx.product.service.ICategoryService;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 商品分类Service业务层处理
 */
@Service
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements ICategoryService {

    @Autowired
    private CategoryMapper categoryMapper;


/*    @Override
    public List<Category> treeSelect(Long id) {
        List<Category> categoryList = categoryMapper.selectList(new LambdaQueryWrapper<Category>().eq(Category::getParentId, id));
        if(!CollectionUtils.isEmpty(categoryList)){
            categoryList.forEach(category -> {
                // TODO  优化处理，不能循环中查询数据库，否则，会发送大量sql语句。
                Long count = categoryMapper.selectCount(new LambdaQueryWrapper<Category>().eq(Category::getParentId, category.getId()));
                if(count>0){
                    category.setHasChildren(true);
                }else{
                    category.setHasChildren(false);
                }
            });
        }
        return categoryList;
    }*/

    @Override
    public List<Category> treeSelect(Long id) {
        List<Category> categoryList = categoryMapper.selectList(new LambdaQueryWrapper<Category>().eq(Category::getParentId, id));
        if(!CollectionUtils.isEmpty(categoryList)){
            // TODO  优化处理，不能循环中查询数据库，否则，会发送大量sql语句。 private Boolean hasChildren = false;
            List<Map<String,Long>> mapList =  categoryMapper.selectMapList(id);

            if(!CollectionUtils.isEmpty(mapList)){
                Map<Long,Long> map = new HashMap();
                mapList.forEach(mapKV -> {
                    map.put(mapKV.get("id"),mapKV.get("count"));
                });
                categoryList.forEach(category -> {
                    if(map.containsKey(category.getId()) && map.get(category.getId()) > 0){
                        category.setHasChildren(true);
                    }else{
                        category.setHasChildren(false);
                    }
                });
            }
        }
        return categoryList;
    }


    /**
     * 根据指定的分类id,获取所有上级id,并存放到集合中返回。
     * @param categoryId 当前分类id
     * @return 当前分类id的所有上级分类id，保证id顺序。一级，二级，三级
     */
    @Override
    public List<Long> getAllCategoryIdList(Long categoryId) {
        List<Long> idList = new ArrayList<>(); // 1 2 3

        List<Category> categoryList = getParent(categoryId,new ArrayList<>()); //顺序   3 2 1
        int size = categoryList.size();
        for (int i = size; i > 0 ; i--) { //颠倒顺序
            Category category = categoryList.get(i-1);
            idList.add(category.getId());
        }
        return idList;
    }

    /**
     * 递归：找当前节点，以及它的所有父级节点
     *      1.三级找二级，二级找一级，这是同类型问题，可以使用递归
     *      2.退出条件。根节点没有父级节点就可以退出。
     * @param categoryId
     * @return
     */
    private List<Category> getParent(Long categoryId,List<Category> categoryList) {
        while (categoryId > 0){ //退出条件
            Category category = categoryMapper.selectById(categoryId); //找自己
            categoryList.add(category);
            return getParent(category.getParentId(),categoryList); //递归
        }
        return categoryList;
    }

    @Override
    public void exportData(HttpServletResponse response) throws Exception {
        //给客户端返回的是什么内容类型数据
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");

        // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
        String fileName = URLEncoder.encode("分类数据", "UTF-8");
        response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
        response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");

        List<Category> categoryList = categoryMapper.selectList(null);
        //类型转换
        List<CategoryExcelVo> categoryExcelVoList = categoryList.stream().map(category -> {
            CategoryExcelVo vo = new CategoryExcelVo();
            BeanUtils.copyProperties(category, vo);
            return vo;
        }).toList();

        //将内存集合数据写到客户端响应流中。以Excel文件进行下载数据
        EasyExcel.write(response.getOutputStream(), CategoryExcelVo.class).sheet("分类数据").doWrite(categoryExcelVoList);
    }


    @Override
    public void importData(MultipartFile file) throws Exception {
        //读取上传的Excel文件行的数据，封装成CategoryExcelVo对象，放在集合中
        List<CategoryExcelVo> categoryExcelVoList = EasyExcel.read(file.getInputStream()).head(CategoryExcelVo.class).sheet().doReadSync();

        //类型转换
        List<Category> categoryList = categoryExcelVoList.stream().map(categoryExcelVo -> {
            Category category = new Category();
            BeanUtils.copyProperties(categoryExcelVo, category);
            return category;
        }).collect(Collectors.toList());

        //将读取集合数据保存到数据库汇总
        this.saveBatch(categoryList);
    }

    //=================================================================
    @Override
    public List<CategoryVo> getCategoryOne() {
        List<Category> categoryList = categoryMapper.selectList(new LambdaQueryWrapper<Category>().eq(Category::getParentId, 0));
        if(!CollectionUtils.isEmpty(categoryList)){
            List<CategoryVo> categoryVoList = categoryList.stream().map(category -> {
                CategoryVo vo = new CategoryVo();
                BeanUtils.copyProperties(category, vo);
                return vo;
            }).toList();
            return categoryVoList;
        }

        return new ArrayList<CategoryVo>();
    }


    @Override
    public List<CategoryVo> tree() {
        List<Category> categoryList = categoryMapper.selectList(null);

            List<CategoryVo> categoryVoList = categoryList.stream().map(category -> {
                CategoryVo vo = new CategoryVo();
                BeanUtils.copyProperties(category, vo);
                return vo;
            }).toList();
            return CategoryHelper.buildTree(categoryVoList); //将703条分类数据，构建好父子关系(树结构)返回

    }
}